package com.upcontrol.uartagent.entity;

import com.csjbot.csjbase.log.Csjlogger;

import java.util.Arrays;

/**
 * Copyright (c) 2017, SuZhou CsjBot. All Rights Reserved.
 * www.csjbot.com
 * <p>
 * Created by 浦耀宗 at 2017/02/09 0009-10:56.
 * Email: puyz@csjbot.com
 */

public abstract class UartPacket implements Packet {
    private byte[] header = new byte[]{(byte) 0xAA};
    private byte srcOrTar = (byte) 0x12;
    private byte ref = (byte) (0x80);
    protected byte[] mContent = new byte[0];

    public byte getCmd() {
        return cmd;
    }

    private byte cmd;
    private int dataLen;
    private byte checksum;

    public void setCmd(byte cmd) {
        this.cmd = cmd;
    }

    private byte getCheck() {
        int dataSum = 0x00;

        if (mContent.length != dataLen) {
            return (byte) dataSum;
        }

        for (int i = 0; i < dataLen; i++) {
            dataSum += mContent[i];
        }

        return (byte) ((header[0] + srcOrTar + ref + cmd + dataLen + dataSum) & 0xFF);
    }

    public abstract byte[] getContent();

    public abstract void setContent(byte[] content);

    /**
     * 数据包编码成byte数组
     *
     * @return btye数组
     * @throws UartException 抛出 RosConnectException异常
     */
    @Override
    public byte[] encodeBytes() {
        byte[] contentData = getContent();
        dataLen = (byte) contentData.length;
        byte[] bytes = new byte[6 + contentData.length];

        int offset = 0;

        System.arraycopy(this.header, 0, bytes, offset, 1);
        offset += 1;
        System.arraycopy(new byte[]{(byte) srcOrTar}, 0, bytes, offset, 1);
        offset += 1;
        System.arraycopy(new byte[]{(byte) ref}, 0, bytes, offset, 1);
        offset += 1;
        System.arraycopy(new byte[]{(byte) cmd}, 0, bytes, offset, 1);
        offset += 1;
        System.arraycopy(new byte[]{(byte) dataLen}, 0, bytes, offset, 1);
        offset += 1;

        if (dataLen > 0) {
            System.arraycopy(contentData, 0, bytes, offset, dataLen);
            offset += dataLen;
        }

        System.arraycopy(new byte[]{getCheck()}, 0, bytes, offset, 1);

        return bytes;
    }

    /**
     * 从byte数组解码数据包
     *
     * @param rawData 原始byte数组
     * @return 解码包
     * @throws UartException 抛出 RosConnectException异常
     */
    @Override
    public Packet decodeBytes(byte[] rawData) {
        srcOrTar = rawData[1];
        ref = rawData[2];
        cmd = rawData[3];
        dataLen = rawData[4];

//        Csjlogger.error("decodeBytes  cmd is  {}", cmd);

        try {
            checksum = rawData[5 + dataLen];
        } catch (IndexOutOfBoundsException e) {
            Csjlogger.error("Packet IndexOutOfBounds ");
            return null;
        }

        if (dataLen < 0) {
            Csjlogger.error("dataLen is {} < 0 ", dataLen);
            return null;
        }

        mContent = Arrays.copyOfRange(rawData, 5, 5 + dataLen);
        setContent(mContent);

        if (getCheck() != checksum) {
            Csjlogger.error("check fail, return null realcheck is {}, getCheck is {}", checksum, getCheck());
            return null;
        }

        return this;
    }


}
